import {forwardRef, useCallback, useImperativeHandle, useMemo, useState} from "react";
import useForceUpdate from "../../hooks/useForceUpdate";

function Counter(props, ref) {
  const [count, setCount] = useState(0)
  const forceUpdate = useForceUpdate()

  // 父组件要拿到子组件提供的一个密钥， 这个密钥是通过count + 一个随机字符串生成的
  // 同时count如果不变，则这个密钥是不会变的
  // ref.current = count + Math.random(); // 每次函数组件的重新渲染都会将它重新赋值，会造成一些问题
  // 第一个参数是ref : 意味着他在底层会去改你这个ref的current属性
  // 第二个参数是一个函数： 这个函数的返回值最终会被丢到这个ref.current属性上去
  // 第三个参数是依赖项： 重头戏 意味着依赖项不变的话 ref的current值不会被重新赋值
  useImperativeHandle(ref, () => {
    return count + Math.random();
  }, [count])
  console.log("props", props.defaultCount)

  // 由于没有给这个getCountValue 做任何性能处理，每次组件的重新渲染都毫无例外的参与了引用的重新创建
  // 不给依赖的后果 始终拿的是首次渲染时的时间切片 count 为0

  // 默认约定俗成的东西都是用useCallback去缓存函数， 虽然useMemo也可以缓存， 但是我们通常不会这样做
  const addCount = useCallback(() => {
    setCount(prev => prev + 1);
  }, [])
  // const getCountValue = () => {
  //   console.log("最新的count value", count)
  // }

  //  useMemo: 第一个参数也是一个函数， 但是他的函数不会被react执行，而是直接进入缓存

  // useMemo: 第一个参数是一个函数，这个函数会被React 直接执行， 然后将其返回值进行缓存
  // 第二个参数是依赖项，当依赖项发生变化时，React会重新执行对应的第一个参数， 然后拿到最新的返回值， 再次进行返回
  //
  // const addCount = useMemo(() => () => {
  //   setCount(prev => prev + 1);
  // }, [])
  const getCountValue = useCallback(() => {
    console.log("最新的count value", count, setCount); // 每一次count导致的重新渲染都导致了了getCountValue 的重新刷新
  }, [count])
  // 依赖是干嘛的： 当依赖发生变化以后 在不同的hook 会有不同的效果
  // 1。useEffect : 导致useEffect 注册函数重新执行
  // 2。useCallback: 导致useCallback对应的函数引用重新生成
  // useMemo 下节课讲
  return (
    <div>
      <span>{count}</span>
      <button onClick={addCount}>add Count</button>
      <button onClick={forceUpdate}>强制刷新Counter组件</button>
    </div>
  )
}

// 所以这里重新生成的button只是虚拟dom,最终决定是否要更改真实dom 是由diff算法决定的

export default forwardRef(Counter);